package com.atyun;

import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.atyun.properties.DtpProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.ByteArrayResource;

import java.util.Objects;
import java.util.Properties;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

@Slf4j
public class NacosListener implements Listener, InitializingBean {

    public static volatile boolean flag = false;

    //注入Naming Server实例，用于注册监听器，监听对应yaml文件
    @NacosInjected
    private ConfigService configService;

    /**
     * 注册监听器
     * @Author: 云水瑶
     * @Date: 2025/4/26
    */
    @Override
    public void afterPropertiesSet() throws Exception {
        //data-id，group，listener
        System.out.println("addListener");
        configService.addListener("dtp.yaml", "DEFAULT_GROUP", this);
    }

    @Override
    public Executor getExecutor() {
        return Executors.newFixedThreadPool(1);
    }

    /**
     * nacos配置发生更改之后进行动态更新处理
     * @Author: 云水瑶
     * @Date: 2025/4/26
    */
    @Override
    public void receiveConfigInfo(String s) {
        String pName = null;
        try {
            if(Objects.isNull(s)) {
                log.error("动态更新错误");
            }
            log.info("配置更新，动态调整目标线程池参数");
            //需要将yaml文件转为properties实例
            YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
            yamlPropertiesFactoryBean.setResources(new ByteArrayResource(s.getBytes()));
            Properties properties = yamlPropertiesFactoryBean.getObject();
            System.out.println(properties);

            DtpProperties dtpProperties = new DtpProperties();
            //将properties转为springboot提供的数据配置绑定源
            ConfigurationPropertySource source = new MapConfigurationPropertySource(properties);
            //再通过binder进行配置绑定
            Binder binder = new Binder(source);
            //创建dtpProperties类型信息
            ResolvableType type = ResolvableType.forClass(DtpProperties.class);
            //创建bindable绑定目标
            Bindable<?> bindable = Bindable.of(type).withExistingValue(dtpProperties);
            //绑定，通过dtp指定前缀
            binder.bind("dtp", bindable);

            //考虑使用CAS机制优化
            for (DtpProperties.DtpExecutorProperties entry : dtpProperties.getExecutor()) {
                DptExecutor dptExecutor = DtpUtil.getDptExecutor(entry.getPoolName());
                pName = entry.getPoolName();
                int tryCount = 0;
                while (tryCount < 3) {
                    //原线程池中的参数
                    int oldCorePoolSize = dptExecutor.getCorePoolSize();
                    int oldMaximumPoolSize = dptExecutor.getMaximumPoolSize();

                    //通过CAS机制比较V与A，然后更新B
                    if (dptExecutor.casUpdateCorePoolSize(oldCorePoolSize, entry.getCorePoolSize())) {
                        dptExecutor.casUpdateMaximumPoolSize(oldMaximumPoolSize, entry.getMaximumPoolSize());
                        log.info("CAS机制保证修改线程池参数成功: {}, core[{} -> {}], max[{} -> {}]",
                                entry.getPoolName(),
                                oldCorePoolSize, entry.getCorePoolSize(),
                                oldMaximumPoolSize, entry.getMaximumPoolSize());
                    }
                    tryCount++;
                    Thread.sleep(10);
                }
            }
            flag = true;
        } catch (Exception e) {
            log.error("动态修改线程池参数失败，失败线程? {}", pName);
            e.printStackTrace();
        }
    }
}


//            DptExecutor dptExecutor = DtpUtil.getDptExecutor(entry.getPoolName());
//            dptExecutor.setCorePoolSize(entry.getCorePoolSize());
//            dptExecutor.setMaximumPoolSize(entry.getMaximumPoolSize());
